home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 2: CDPD 1 / Almathera Ten on Ten - Disc 2: CDPD 1.iso / pd / 276-300 / 294 / fmsdisk / fms.c < prev    next >
C/C++ Source or Header  |  1995-03-14  |  9KB  |  396 lines

  1.  
  2. /*
  3.  *  FMS.C
  4.  *
  5.  *  File Disk Device (fmsdisk.device)
  6.  *
  7.  *  Simulates a trackdisk by using a large file to hold the 'blocks'.
  8.  */
  9.  
  10. #include <exec/types.h>
  11. #include <exec/nodes.h>
  12. #include <exec/errors.h>
  13. #include <exec/memory.h>
  14. #include <devices/trackdisk.h>
  15. #include <libraries/dos.h>
  16. #include <libraries/dosextens.h>
  17.  
  18. #include <proto/all.h>
  19.  
  20. /*#define DEBUG*/
  21.  
  22. #define CMD_OPENUNIT    (0x7FF0 & ~TDF_EXTCOM)
  23. #define CMD_CLOSEUNIT    (0x7FF1 & ~TDF_EXTCOM)
  24. #define CMD_KILLPROC    (0x7FF2 & ~TDF_EXTCOM)
  25.  
  26. void SynchroMsg();
  27. void ExtendSize();
  28.  
  29. typedef struct Library    LIB;
  30. typedef struct Device    DEV;
  31. typedef struct Process    PROC;
  32. typedef struct MsgPort    PORT;
  33. typedef struct Message    MSG;
  34. typedef struct List    LIST;
  35. typedef struct Node    NODE;
  36. typedef long (*func_ptr)();
  37.  
  38. typedef struct {
  39.     struct  Unit    U;
  40.     UWORD   OpenCnt;
  41.     long    Fh;     /*  file handle     */
  42.     long    Size;    /*  current size    */
  43.     char    NotSyn;
  44.     char    Reserved;
  45. } NDUnit;
  46.  
  47. typedef struct {
  48.     LIB     Lib;
  49.     NDUnit  Unit[32];
  50. } NDev;
  51.  
  52. typedef struct {
  53.     struct  Message io_Message;
  54.     struct  Device  *io_Device;     /* device node pointer  */
  55.     struct  Unit    *io_Unit;        /* unit (driver private)*/
  56.     UWORD   io_Command;         /* device command */
  57.     UBYTE   io_Flags;
  58.     BYTE    io_Error;            /* error or warning num */
  59.     ULONG   io_Actual;            /* actual number of bytes transferred */
  60.     ULONG   io_Length;            /* requested number bytes transferred*/
  61.     APTR    io_Data;            /* points to data area */
  62.     ULONG   io_Offset;            /* offset for block structured devices */
  63.  
  64.     long    iotd_Count;         /*    (extension)     */
  65.     long    iotd_SecLabel;        /*    (extension)     */
  66. } IOB;
  67.  
  68. extern char DeviceName[];
  69. extern char IdString[];
  70. extern void DUMmySeg();
  71.  
  72. typedef NDev    *NDevP;
  73. typedef IOB    *IOBP;
  74.  
  75. long SysBase    = NULL;
  76. NDev *DevBase    = NULL;
  77. APTR DevSegment = NULL;
  78. PORT *FProc    = NULL;
  79. PORT FPort;
  80.  
  81. extern func_ptr DevVectors[];
  82.  
  83. __saveds NDevP    __asm
  84. Init(register __a0 APTR seg)
  85. {
  86.     NDev *db;
  87.  
  88.     SysBase = *(long *)4;
  89.     DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 0);
  90.  
  91.     DevBase = db = (NDev *)MakeLibrary((long **)DevVectors,NULL,NULL,sizeof(NDev),NULL);
  92.     db->Lib.lib_Node.ln_Type = NT_DEVICE;
  93.     db->Lib.lib_Node.ln_Name = DeviceName;
  94.     db->Lib.lib_Flags = LIBF_CHANGED|LIBF_SUMUSED;
  95.     db->Lib.lib_Version = 1;
  96.     db->Lib.lib_IdString= (APTR)IdString;
  97.  
  98.     DevSegment = seg;
  99.     AddDevice((DEV *)db);
  100.     return(db);
  101. }
  102.  
  103. __saveds NDevP __asm
  104. DevOpen(register __d0 long unitnum,
  105.     register __a1 IOBP iob,
  106.     register __d1 long flags
  107.        )
  108. {
  109.     NDev *nd = DevBase;
  110.     NDUnit *unit = &nd->Unit[unitnum];
  111.  
  112.     if (++nd->Lib.lib_OpenCnt == 1) {
  113.     FProc = CreateProc("FMS-Dummy", 0, (long)DUMmySeg >> 2, 4096);
  114.     FPort.mp_SigBit = SIGBREAKB_CTRL_D;    /*  port init */
  115.     FPort.mp_SigTask= FProc->mp_SigTask;
  116.     FPort.mp_Flags = PA_SIGNAL;
  117.     NewList(&FPort.mp_MsgList);
  118.     }
  119.  
  120.     if (++unit->OpenCnt == 1)
  121.     SynchroMsg(CMD_OPENUNIT, unit);
  122.  
  123.     nd->Lib.lib_Flags &= ~LIBF_DELEXP;
  124.     iob->io_Unit = (struct Unit *)unit;
  125.     iob->io_Error = 0;
  126.     return(nd);
  127. }
  128.  
  129.  
  130. __saveds APTR
  131. DevExpunge()
  132. {
  133.     NDev *nd = DevBase;
  134.  
  135.     if (DevSegment == NULL)
  136.     Alert(24, (char *)24);
  137.     if (nd->Lib.lib_OpenCnt) {
  138.     nd->Lib.lib_Flags |= LIBF_DELEXP;
  139.     return(NULL);
  140.     }
  141.     Remove((NODE *)nd);
  142.     FreeMem((char *)nd - nd->Lib.lib_NegSize, nd->Lib.lib_NegSize + nd->Lib.lib_PosSize);
  143.     DevSegment = NULL;
  144.     return(DevSegment);
  145. }
  146.  
  147. __saveds APTR __asm
  148. DevClose(register __a1 IOBP iob)
  149. {
  150.     NDev *nd = DevBase;
  151.  
  152.     {
  153.     NDUnit *unit = (NDUnit *)iob->io_Unit;
  154.     if (unit->OpenCnt && --unit->OpenCnt == 0)
  155.         SynchroMsg(CMD_CLOSEUNIT, unit);
  156.     }
  157.  
  158.     if (nd->Lib.lib_OpenCnt && --nd->Lib.lib_OpenCnt)
  159.     return(NULL);
  160.     if (FProc) {
  161.     SynchroMsg(CMD_KILLPROC, NULL);
  162.     FProc = NULL;
  163.     }
  164.     if (nd->Lib.lib_Flags & LIBF_DELEXP)
  165.     return(DevExpunge());
  166.     /*
  167.      *    close down resources
  168.      */
  169.     return(NULL);
  170. }
  171.  
  172. __saveds void __asm
  173. DevBeginIO(register __a1 IOBP iob)
  174. {
  175.     /*NDev *nd = DevBase;*/
  176.  
  177.     iob->io_Error = 0;
  178.     iob->io_Actual = 0;
  179.  
  180.     switch(iob->io_Command & ~TDF_EXTCOM) {
  181.     case CMD_INVALID:
  182.     iob->io_Error = IOERR_NOCMD;
  183.     break;
  184.     case CMD_RESET:
  185.     break;
  186.     case CMD_READ:
  187.     PutMsg(&FPort, &iob->io_Message);
  188.     iob->io_Flags &= ~IOF_QUICK;    /*  not quick */
  189.     iob = NULL;
  190.     break;
  191.     case CMD_WRITE:
  192.     PutMsg(&FPort, &iob->io_Message);
  193.     iob->io_Flags &= ~IOF_QUICK;    /*  not quick */
  194.     iob = NULL;
  195.     break;
  196.     case CMD_UPDATE:
  197.     break;
  198.     case CMD_CLEAR:
  199.     break;
  200.     case CMD_STOP:
  201.     break;
  202.     case CMD_START:
  203.     break;
  204.     case CMD_FLUSH:
  205.     break;
  206.     case TD_MOTOR:        /*    motor,    no action   */
  207.     case TD_SEEK:        /*    seek,    no action   */
  208.     break;
  209.     case TD_FORMAT:        /*    format            */
  210.     PutMsg(&FPort, &iob->io_Message);
  211.     iob->io_Flags &= ~IOF_QUICK;    /*  not quick */
  212.     iob = NULL;
  213.     break;
  214.     case TD_REMOVE:        /*    not supported        */
  215.     iob->io_Error = IOERR_NOCMD;
  216.     break;
  217.     case TD_CHANGENUM:        /*    change count never changes  */
  218.     iob->io_Actual = 1;
  219.     break;
  220.     case TD_CHANGESTATE:    /*    0=disk in drive     */
  221.     iob->io_Actual = 0;
  222.     break;
  223.     case TD_PROTSTATUS:     /*    io_Actual -> 0 (rw) */
  224.     iob->io_Actual = 0;
  225.     break;
  226.     case TD_RAWREAD:        /*    not supported        */
  227.     case TD_RAWWRITE:
  228.     iob->io_Error = IOERR_NOCMD;
  229.     break;
  230.     case TD_GETDRIVETYPE:   /*    drive type?        */
  231.     iob->io_Actual = 0;
  232.     break;
  233.     case TD_GETNUMTRACKS:
  234.     iob->io_Actual = 0; /*    # of tracks?        */
  235.     break;
  236.     case TD_ADDCHANGEINT:   /*    action never taken  */
  237.     case TD_REMCHANGEINT:
  238.     break;
  239.     default:
  240.     iob->io_Error = IOERR_NOCMD;
  241.     break;
  242.     }
  243.     if (iob) {
  244.     if ((iob->io_Flags & IOF_QUICK) == 0)
  245.         ReplyMsg((MSG *)iob);
  246.     }
  247. }
  248.  
  249. __saveds void __asm
  250. DevAbortIO(register __a1 IOBP iob)
  251. {
  252.     /*NDev *nd = DevBase;*/
  253. }
  254.  
  255. func_ptr DevVectors[] = {
  256.     (func_ptr)DevOpen,
  257.     (func_ptr)DevClose,
  258.     (func_ptr)DevExpunge,
  259.     NULL,
  260.     (func_ptr)DevBeginIO,
  261.     (func_ptr)DevAbortIO,
  262.     (func_ptr)-1
  263. };
  264.  
  265. /*
  266.  *  Server communications
  267.  */
  268.  
  269. void
  270. SynchroMsg(cmd, unit)
  271. UWORD cmd;
  272. struct Unit *unit;
  273. {
  274.     IOB Iob;
  275.  
  276.     Iob.io_Message.mn_ReplyPort = CreatePort(NULL, 0);
  277.     Iob.io_Command = cmd;
  278.     Iob.io_Unit = unit;
  279.  
  280.     PutMsg(&FPort, &Iob.io_Message);
  281.     WaitPort(Iob.io_Message.mn_ReplyPort);
  282.     DeletePort(Iob.io_Message.mn_ReplyPort);
  283. }
  284.  
  285. /*
  286.  *    SERVER SIDE (IS A PROCESS)
  287.  *
  288.  *    File name is:
  289.  */
  290.  
  291. __saveds void
  292. CoProc()
  293. {
  294.     IOBP iob;
  295.     NDUnit *unit;
  296.     char buf[128];
  297.     char notdone = 1;
  298. #ifdef DEBUG
  299.     long fh = Open("con:0/0/320/100/Debug", 1006);
  300. #endif
  301.  
  302.     Wait(SIGBREAKF_CTRL_D);     /*  wait for port init  */
  303.  
  304.     while (notdone) {
  305.     WaitPort(&FPort);
  306.     while (iob = (IOBP)GetMsg(&FPort)) {
  307.         unit = (NDUnit *)iob->io_Unit;
  308.  
  309. #ifdef DEBUG
  310.         sprintf(buf, "Cmd %08lx/%04x @ %08lx Buf %08lx %04x\n",
  311.         unit, iob->io_Command, iob->io_Offset, iob->io_Data, iob->io_Length
  312.         );
  313.         Write(fh, buf, strlen(buf));
  314. #endif
  315.         switch(iob->io_Command & ~TDF_EXTCOM) {
  316.         case CMD_OPENUNIT:
  317.         sprintf(buf, "FMS:Unit%d", unit - &DevBase->Unit[0]);
  318.         unit->Fh = Open(buf, 1005);
  319.         if (unit->Fh == NULL) {
  320.             unit->Fh = Open(buf, 1006);
  321.             unit->NotSyn = 1;
  322.         }
  323.         if (unit->Fh) {
  324.             Seek(unit->Fh, 0L, 1);
  325.             unit->Size = Seek(unit->Fh, 0L, -1);
  326.         }
  327.         break;
  328.         case CMD_CLOSEUNIT:
  329.         if (unit->Fh) {
  330.             Close(unit->Fh);
  331.             unit->Fh = NULL;
  332.         }
  333.         break;
  334.         case CMD_KILLPROC:
  335.         notdone = 0;
  336.         break;
  337.         case CMD_READ:
  338.         if (unit->Fh == NULL)
  339.             break;
  340.         if (iob->io_Offset + iob->io_Length > unit->Size)
  341.             ExtendSize(unit, iob->io_Offset + iob->io_Length);
  342.         Seek(unit->Fh, iob->io_Offset, -1);
  343.         iob->io_Actual = Read(unit->Fh, (char *)iob->io_Data, iob->io_Length);
  344.         break;
  345.         case CMD_WRITE:
  346.         /*
  347.          *  This causes file to be closed/reopened after
  348.          *  formatting.
  349.          */
  350.         if (unit->NotSyn && unit->Fh) {
  351.             Close(unit->Fh);
  352.             sprintf(buf, "FMS:Unit%d", unit - &DevBase->Unit[0]);
  353.             unit->Fh = Open(buf, 1005);
  354.             unit->NotSyn = 0;
  355.         }
  356.         /* fall through */
  357.         case TD_FORMAT:
  358.         if (unit->Fh == NULL)
  359.             break;
  360.  
  361.         if (iob->io_Offset > unit->Size)
  362.             ExtendSize(unit, iob->io_Offset);
  363.         Seek(unit->Fh, iob->io_Offset, -1);
  364.         iob->io_Actual = Write(unit->Fh, (char *)iob->io_Data, iob->io_Length);
  365.         break;
  366.         }
  367.  
  368.         if (notdone == 0)       /*  forbid before falling through */
  369.         Forbid();           /*  and esp before replying       */
  370.         ReplyMsg(&iob->io_Message);
  371.     }
  372.     }
  373.     /* fall through to exit */
  374. }
  375.  
  376. void
  377. ExtendSize(unit, offset)
  378. NDUnit *unit;
  379. long offset;
  380. {
  381.     long pos;
  382.     char *buf = AllocMem(512, MEMF_CLEAR|MEMF_PUBLIC);
  383.  
  384.     if (unit->NotSyn == 0)
  385.     unit->NotSyn = 1;
  386.     Seek(unit->Fh, 0L, 1);
  387.     pos = Seek(unit->Fh, 0L, 0);
  388.     while (pos < offset) {
  389.     if (Write(unit->Fh, buf, 512) != 512)
  390.         break;
  391.     pos += 512;
  392.     }
  393.     FreeMem(buf, 512);
  394. }
  395.  
  396.